/*
 ------------------------------------------------------------------------------
 Copyright (C) 2006-2007 Team Blur.

 This file is part of the Quantum Engine source code.

 The Quantum Engine source code is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or (at your
 option) any later version.

 The Quantum Engine source code is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 more details.

 You should have received a copy of the GNU General Public License along with
 the Quantum Engine source code; if not, write to the Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 ------------------------------------------------------------------------------
*/


#ifndef __CG_LOCAL_H__
#define __CG_LOCAL_H__


#include "../game.h"
#include "cg_public.h"


#define LAG_SAMPLES				128
#define LAG_WIDTH				64
#define LAG_HEIGHT				64

// The parseEntities array must be large enough to hold PACKET_BACKUP snapshots
// of entities, so that when a delta compressed message arrives from the server
// it can be un-delta'ed from the original
#define	MAX_PARSE_ENTITIES		PACKET_BACKUP * MAX_SNAPSHOT_ENTITIES

typedef struct {
	bool				valid;

	int					time;
	int					ping;
	bool				rateDelayed;

	int					deltaMessage;
	int					messageSequence;

	playerState_t		state;

	int					numEntities;
	int					parseEntitiesNum;
} snapshot_t;

typedef struct {
	entityState_t		current;
	entityState_t		previous;

	int					entityHandle;		// Render entity handle
	int					lightHandle;		// Render light handle
	int					emitterHandle;		// Sound emitter handle
} cgEntity_t;

typedef struct {
	int					dropped;
	int					suppressed;
	int					ping;
} lagSamples_t;

typedef struct {
	lagSamples_t		samples[LAG_SAMPLES];
	int					current;

	byte				image[LAG_HEIGHT][LAG_WIDTH][4];
} lagometer_t;

typedef struct {
	model_t *			model;
	clipModel_t *		clipModel;

	int					contents;
	odBounds			bounds;
} cgModel_t;

typedef struct {
	material_t *		whiteMaterial;
	material_t *		charsetMaterial;
} cgMedia_t;

// The cg structure will be cleared during a map restart
typedef struct {
	int					time;
	int					realTime;

	int					frameTime;
	int					frameCount;

	cgEntity_t			entities[MAX_ENTITIES];

	int					deltaAngles[3];

	// View rendering
	renderView_t		renderView;
	odAngles			renderViewAngles;

	odVec3				velocity;

	bool				firstSnapshot;

	// Development tools
	lagometer_t			lagometer;

	bool				testModel;
	bool				testModelGun;
	renderEntity_t		testModelEntity;
	int					testModelEntityHandle;
	renderView_t		testModelView;
	float				testModelFovX;
	float				testModelFovY;

	bool				testPostProcess;
	material_t *		testPostProcessMaterial;

	bool				testSound;
	soundShader_t *		testSoundShader;
	odVec3				testSoundOrigin;
	int					testSoundEmitterHandle;
	int					testSoundParticleHandle;
} cg_t;

// The cgs structure holds everything loaded or calculated from the game state.
// It will not be cleared during map restarts, allowing all clients to begin
// playing instantly.
typedef struct {
	bool				demoPlaying;

	glConfig_t			glConfig;
	alConfig_t			alConfig;

	cgMedia_t			media;				// Local media

	scene_t *			scene;

	// Files specified by the server
	model_t *			gameModels[MAX_GAME_MODELS];
	clipModel_t *		gameClipModels[MAX_GAME_CLIP_MODELS];

	material_t *		gameMaterials[MAX_GAME_MATERIALS];
	soundShader_t *		gameSoundShaders[MAX_GAME_SOUND_SHADERS];

	// Game state from server
	const char *		configStrings[MAX_CONFIG_STRINGS];

	snapshot_t			snapshot;
	snapshot_t			snapshots[PACKET_BACKUP];

	entityState_t *		baselines;
	entityState_t *		parseEntities;
	int					parseEntitiesNum;
} cgs_t;

extern cg_t				cg;
extern cgs_t			cgs;
extern cgExport_t		cge;
extern cgImport_t *		cgi;

extern cvar_t *			cg_footSteps;
extern cvar_t *			cg_noRender;
extern cvar_t *			cg_showMiss;
extern cvar_t *			cg_showDeltaEntities;
extern cvar_t *			cg_showViewPos;
extern cvar_t *			cg_showMaterial;
extern cvar_t *			cg_viewBlend;
extern cvar_t *			cg_particles;
extern cvar_t *			cg_muzzleFlashes;
extern cvar_t *			cg_decals;
extern cvar_t *			cg_ejectBrass;
extern cvar_t *			cg_blood;
extern cvar_t *			cg_shells;
extern cvar_t *			cg_drawPlayerShadow;
extern cvar_t *			cg_testGunX;
extern cvar_t *			cg_testGunY;
extern cvar_t *			cg_testGunZ;
extern cvar_t *			cg_testModelRotate;
extern cvar_t *			cg_crosshairX;
extern cvar_t *			cg_crosshairY;
extern cvar_t *			cg_crosshairSize;
extern cvar_t *			cg_crosshairColor;
extern cvar_t *			cg_crosshairAlpha;
extern cvar_t *			cg_crosshairHealth;
extern cvar_t *			cg_crosshairNames;
extern cvar_t *			cg_draw2D;
extern cvar_t *			cg_drawCrosshair;
extern cvar_t *			cg_drawLagometer;
extern cvar_t *			cg_drawDisconnected;
extern cvar_t *			cg_spectator;
extern cvar_t *			cg_autoSwitch;
extern cvar_t *			cg_autoReload;
extern cvar_t *			cg_drawGun;
extern cvar_t *			cg_fov;
extern cvar_t *			cg_predict;

void			CG_LoadLights (void);

bool			CG_ParseSnapshot (int sequence, ByteBuffer *msg, int *time, bool *deltaCompressed);

void			CG_ShowMaterial (void);

void			CG_AddEntities (void);

void			CG_AddGameCommands (void);
void			CG_RemoveGameCommands (void);


#endif	// __CG_LOCAL_H__
